#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
观察者模式 (Observer Pattern) - Python实现详解

概述引导：
观察者模式定义对象间的一对多依赖关系，当一个对象状态改变时，
所有依赖它的对象都会得到通知并自动更新。

学习要点：
1. 传统观察者模式实现
2. Python事件系统实现
3. 装饰器观察者模式
4. 异步观察者模式

Java对比要点：
- Java有Observable类和Observer接口
- Python更灵活，可以用多种方式实现
- Python支持函数作为观察者
- Python的事件系统更简洁

关键理解：
观察者模式实现松耦合的通知机制，Python的实现更加灵活多样。
"""

from abc import ABC, abstractmethod
from typing import Any, Callable, Dict, List, Optional, Set, Union
from dataclasses import dataclass, field
from enum import Enum
from datetime import datetime
import asyncio
import threading
import weakref
from functools import wraps
import json


# ============= 传统观察者模式 =============

class Observer(ABC):
    """
    观察者抽象基类
    
    Java对比：
    - Java有Observer接口
    - Python使用ABC更灵活
    """
    
    @abstractmethod
    def update(self, subject: 'Subject', event_data: Any = None):
        """接收通知并更新"""
        pass


class Subject(ABC):
    """
    主题抽象基类
    
    Java对比：
    - Java有Observable类
    - Python实现更简洁
    """
    
    def __init__(self):
        self._observers: Set[Observer] = set()
    
    def attach(self, observer: Observer):
        """添加观察者"""
        self._observers.add(observer)
    
    def detach(self, observer: Observer):
        """移除观察者"""
        self._observers.discard(observer)
    
    def notify(self, event_data: Any = None):
        """通知所有观察者"""
        for observer in self._observers.copy():  # 复制集合避免迭代时修改
            try:
                observer.update(self, event_data)
            except Exception as e:
                print(f"观察者更新失败: {e}")
    
    def get_observer_count(self) -> int:
        """获取观察者数量"""
        return len(self._observers)


# ============= 具体实现 =============

class EventType(Enum):
    """事件类型枚举"""
    PRICE_CHANGED = "price_changed"
    STOCK_UPDATED = "stock_updated"
    PRODUCT_ADDED = "product_added"
    PRODUCT_REMOVED = "product_removed"
    USER_REGISTERED = "user_registered"
    ORDER_PLACED = "order_placed"


@dataclass
class EventData:
    """事件数据"""
    event_type: EventType
    timestamp: datetime = field(default_factory=datetime.now)
    data: Dict[str, Any] = field(default_factory=dict)
    source: str = ""
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            'event_type': self.event_type.value,
            'timestamp': self.timestamp.isoformat(),
            'data': self.data,
            'source': self.source
        }


class Product(Subject):
    """
    产品类 - 具体主题
    
    当产品信息发生变化时通知观察者
    """
    
    def __init__(self, product_id: str, name: str, price: float, stock: int):
        super().__init__()
        self._product_id = product_id
        self._name = name
        self._price = price
        self._stock = stock
    
    @property
    def product_id(self) -> str:
        return self._product_id
    
    @property
    def name(self) -> str:
        return self._name
    
    @property
    def price(self) -> float:
        return self._price
    
    @price.setter
    def price(self, new_price: float):
        if new_price != self._price:
            old_price = self._price
            self._price = new_price
            
            event_data = EventData(
                event_type=EventType.PRICE_CHANGED,
                data={
                    'product_id': self._product_id,
                    'old_price': old_price,
                    'new_price': new_price,
                    'change_percent': ((new_price - old_price) / old_price) * 100
                },
                source=f"Product({self._product_id})"
            )
            self.notify(event_data)
    
    @property
    def stock(self) -> int:
        return self._stock
    
    @stock.setter
    def stock(self, new_stock: int):
        if new_stock != self._stock:
            old_stock = self._stock
            self._stock = new_stock
            
            event_data = EventData(
                event_type=EventType.STOCK_UPDATED,
                data={
                    'product_id': self._product_id,
                    'old_stock': old_stock,
                    'new_stock': new_stock,
                    'is_out_of_stock': new_stock == 0,
                    'is_low_stock': 0 < new_stock <= 5
                },
                source=f"Product({self._product_id})"
            )
            self.notify(event_data)
    
    def __str__(self):
        return f"Product({self._product_id}, {self._name}, ¥{self._price}, 库存:{self._stock})"


class PriceMonitor(Observer):
    """
    价格监控器 - 具体观察者
    
    监控产品价格变化
    """
    
    def __init__(self, name: str):
        self.name = name
        self.price_history = []
    
    def update(self, subject: Subject, event_data: EventData = None):
        """接收价格变化通知"""
        if event_data and event_data.event_type == EventType.PRICE_CHANGED:
            data = event_data.data
            self.price_history.append({
                'timestamp': event_data.timestamp,
                'product_id': data['product_id'],
                'old_price': data['old_price'],
                'new_price': data['new_price'],
                'change_percent': data['change_percent']
            })
            
            print(f"[{self.name}] 价格变化警报:")
            print(f"  产品: {data['product_id']}")
            print(f"  价格: ¥{data['old_price']:.2f} -> ¥{data['new_price']:.2f}")
            print(f"  变化: {data['change_percent']:+.2f}%")
    
    def get_price_history(self) -> List[Dict[str, Any]]:
        """获取价格历史"""
        return self.price_history.copy()


class StockAlert(Observer):
    """
    库存警报 - 具体观察者
    
    监控库存变化并发出警报
    """
    
    def __init__(self, name: str, low_stock_threshold: int = 5):
        self.name = name
        self.low_stock_threshold = low_stock_threshold
        self.alerts = []
    
    def update(self, subject: Subject, event_data: EventData = None):
        """接收库存变化通知"""
        if event_data and event_data.event_type == EventType.STOCK_UPDATED:
            data = event_data.data
            
            alert_info = {
                'timestamp': event_data.timestamp,
                'product_id': data['product_id'],
                'stock_level': data['new_stock'],
                'alert_type': None
            }
            
            if data['is_out_of_stock']:
                alert_info['alert_type'] = 'OUT_OF_STOCK'
                print(f"[{self.name}] 🚨 缺货警报: 产品 {data['product_id']} 已售罄!")
            elif data['is_low_stock']:
                alert_info['alert_type'] = 'LOW_STOCK'
                print(f"[{self.name}] ⚠️ 低库存警报: 产品 {data['product_id']} 库存仅剩 {data['new_stock']} 件")
            else:
                alert_info['alert_type'] = 'STOCK_NORMAL'
                print(f"[{self.name}] ✅ 库存正常: 产品 {data['product_id']} 库存 {data['new_stock']} 件")
            
            self.alerts.append(alert_info)
    
    def get_alerts(self) -> List[Dict[str, Any]]:
        """获取所有警报"""
        return self.alerts.copy()


class SalesAnalyzer(Observer):
    """
    销售分析器 - 具体观察者
    
    分析产品变化趋势
    """
    
    def __init__(self, name: str):
        self.name = name
        self.analytics_data = {
            'price_changes': 0,
            'stock_changes': 0,
            'total_events': 0,
            'products_tracked': set()
        }
    
    def update(self, subject: Subject, event_data: EventData = None):
        """接收事件并进行分析"""
        if not event_data:
            return
        
        self.analytics_data['total_events'] += 1
        
        if event_data.event_type == EventType.PRICE_CHANGED:
            self.analytics_data['price_changes'] += 1
            product_id = event_data.data['product_id']
            self.analytics_data['products_tracked'].add(product_id)
            
            change_percent = event_data.data['change_percent']
            if abs(change_percent) > 10:
                print(f"[{self.name}] 📊 重大价格变动: {product_id} 变化 {change_percent:+.2f}%")
        
        elif event_data.event_type == EventType.STOCK_UPDATED:
            self.analytics_data['stock_changes'] += 1
            product_id = event_data.data['product_id']
            self.analytics_data['products_tracked'].add(product_id)
    
    def get_analytics(self) -> Dict[str, Any]:
        """获取分析数据"""
        analytics = self.analytics_data.copy()
        analytics['products_tracked'] = len(analytics['products_tracked'])
        return analytics


# ============= Python事件系统 =============

class EventSystem:
    """
    事件系统 - Python特色实现
    
    Python优势：
    - 支持函数作为观察者
    - 事件类型灵活
    - 支持优先级
    """
    
    def __init__(self):
        self._listeners: Dict[str, List[Dict[str, Any]]] = {}
        self._global_listeners: List[Dict[str, Any]] = []
    
    def on(self, event_type: str, callback: Callable, priority: int = 0):
        """注册事件监听器"""
        if event_type not in self._listeners:
            self._listeners[event_type] = []
        
        listener_info = {
            'callback': callback,
            'priority': priority
        }
        
        self._listeners[event_type].append(listener_info)
        # 按优先级排序（高优先级先执行）
        self._listeners[event_type].sort(key=lambda x: x['priority'], reverse=True)
    
    def off(self, event_type: str, callback: Callable):
        """移除事件监听器"""
        if event_type in self._listeners:
            self._listeners[event_type] = [
                listener for listener in self._listeners[event_type]
                if listener['callback'] != callback
            ]
    
    def on_any(self, callback: Callable, priority: int = 0):
        """注册全局事件监听器"""
        listener_info = {
            'callback': callback,
            'priority': priority
        }
        self._global_listeners.append(listener_info)
        self._global_listeners.sort(key=lambda x: x['priority'], reverse=True)
    
    def emit(self, event_type: str, data: Any = None):
        """触发事件"""
        event_data = {
            'type': event_type,
            'data': data,
            'timestamp': datetime.now()
        }
        
        # 执行特定事件监听器
        if event_type in self._listeners:
            for listener in self._listeners[event_type]:
                try:
                    listener['callback'](event_data)
                except Exception as e:
                    print(f"事件监听器执行失败: {e}")
        
        # 执行全局监听器
        for listener in self._global_listeners:
            try:
                listener['callback'](event_data)
            except Exception as e:
                print(f"全局监听器执行失败: {e}")
    
    def get_listener_count(self, event_type: str = None) -> int:
        """获取监听器数量"""
        if event_type:
            return len(self._listeners.get(event_type, []))
        else:
            total = sum(len(listeners) for listeners in self._listeners.values())
            return total + len(self._global_listeners)


# ============= 装饰器观察者 =============

def observable_property(event_name: str = None):
    """
    可观察属性装饰器 - Python特色实现
    
    自动为属性变化生成事件
    """
    def decorator(func):
        property_name = func.__name__
        private_name = f"_{property_name}"
        event_name_final = event_name or f"{property_name}_changed"
        
        def getter(self):
            return getattr(self, private_name, None)
        
        def setter(self, value):
            old_value = getattr(self, private_name, None)
            if old_value != value:
                setattr(self, private_name, value)
                
                # 触发事件
                if hasattr(self, '_event_system'):
                    self._event_system.emit(event_name_final, {
                        'property': property_name,
                        'old_value': old_value,
                        'new_value': value,
                        'object': self
                    })
        
        return property(getter, setter)
    
    return decorator


class ObservableModel:
    """
    可观察模型基类
    
    使用装饰器实现属性观察
    """
    
    def __init__(self):
        self._event_system = EventSystem()
    
    def on(self, event_type: str, callback: Callable, priority: int = 0):
        """注册事件监听器"""
        self._event_system.on(event_type, callback, priority)
    
    def off(self, event_type: str, callback: Callable):
        """移除事件监听器"""
        self._event_system.off(event_type, callback)
    
    def emit(self, event_type: str, data: Any = None):
        """触发事件"""
        self._event_system.emit(event_type, data)


class User(ObservableModel):
    """
    用户模型 - 使用装饰器观察者
    """
    
    def __init__(self, user_id: str, name: str, email: str):
        super().__init__()
        self._user_id = user_id
        self._name = name
        self._email = email
        self._status = "active"
        self._login_count = 0
    
    @property
    def user_id(self) -> str:
        return self._user_id
    
    @observable_property("name_changed")
    def name(self) -> str:
        pass
    
    @observable_property("email_changed")
    def email(self) -> str:
        pass
    
    @observable_property("status_changed")
    def status(self) -> str:
        pass
    
    def login(self):
        """用户登录"""
        self._login_count += 1
        self.emit("user_login", {
            'user_id': self._user_id,
            'login_count': self._login_count,
            'timestamp': datetime.now()
        })
    
    def __str__(self):
        return f"User({self._user_id}, {self.name}, {self.email}, {self.status})"


# ============= 异步观察者 =============

class AsyncObserver(ABC):
    """
    异步观察者抽象基类
    """
    
    @abstractmethod
    async def update_async(self, subject: 'AsyncSubject', event_data: Any = None):
        """异步更新方法"""
        pass


class AsyncSubject:
    """
    异步主题类
    
    Python特色：
    - 支持异步通知
    - 并发处理观察者
    """
    
    def __init__(self):
        self._observers: Set[AsyncObserver] = set()
    
    def attach(self, observer: AsyncObserver):
        """添加异步观察者"""
        self._observers.add(observer)
    
    def detach(self, observer: AsyncObserver):
        """移除异步观察者"""
        self._observers.discard(observer)
    
    async def notify_async(self, event_data: Any = None):
        """异步通知所有观察者"""
        if not self._observers:
            return
        
        # 并发执行所有观察者的更新
        tasks = []
        for observer in self._observers.copy():
            task = asyncio.create_task(observer.update_async(self, event_data))
            tasks.append(task)
        
        # 等待所有任务完成
        results = await asyncio.gather(*tasks, return_exceptions=True)
        
        # 处理异常
        for i, result in enumerate(results):
            if isinstance(result, Exception):
                print(f"异步观察者更新失败: {result}")


class AsyncEmailNotifier(AsyncObserver):
    """
    异步邮件通知器
    """
    
    def __init__(self, name: str):
        self.name = name
        self.sent_emails = []
    
    async def update_async(self, subject: AsyncSubject, event_data: Any = None):
        """异步发送邮件"""
        # 模拟异步邮件发送
        await asyncio.sleep(0.1)  # 模拟网络延迟
        
        email_info = {
            'timestamp': datetime.now(),
            'recipient': 'user@example.com',
            'subject': f'事件通知: {event_data}',
            'status': 'sent'
        }
        
        self.sent_emails.append(email_info)
        print(f"[{self.name}] 📧 异步邮件已发送: {event_data}")


class AsyncLogWriter(AsyncObserver):
    """
    异步日志写入器
    """
    
    def __init__(self, name: str):
        self.name = name
        self.logs = []
    
    async def update_async(self, subject: AsyncSubject, event_data: Any = None):
        """异步写入日志"""
        # 模拟异步文件写入
        await asyncio.sleep(0.05)
        
        log_entry = {
            'timestamp': datetime.now(),
            'level': 'INFO',
            'message': f'事件记录: {event_data}',
            'source': self.name
        }
        
        self.logs.append(log_entry)
        print(f"[{self.name}] 📝 异步日志已记录: {event_data}")


# ============= 演示函数 =============

def demonstrate_traditional_observer():
    """
    演示传统观察者模式
    
    概述引导：
    展示传统观察者模式的实现，包括主题和观察者
    的定义、注册、通知机制。
    
    学习要点：
    1. 主题和观察者的接口设计
    2. 观察者的注册和移除
    3. 事件数据的传递
    4. 异常处理机制
    
    关键理解：
    观察者模式实现了松耦合的通知机制。
    """
    print("=== 传统观察者模式演示 ===")
    print("\n学习目标：")
    print("- 理解观察者模式的结构")
    print("- 掌握主题和观察者的交互")
    print("- 学习事件通知机制")
    print("\n重点概念：")
    print("- 一对多的依赖关系")
    print("- 松耦合的设计")
    print("- 自动通知更新")
    print("=" * 50)
    
    # 创建产品
    product = Product("P001", "iPhone 15", 6999.0, 100)
    
    # 创建观察者
    price_monitor = PriceMonitor("价格监控系统")
    stock_alert = StockAlert("库存警报系统")
    sales_analyzer = SalesAnalyzer("销售分析系统")
    
    # 注册观察者
    product.attach(price_monitor)
    product.attach(stock_alert)
    product.attach(sales_analyzer)
    
    print(f"\n初始产品状态: {product}")
    print(f"观察者数量: {product.get_observer_count()}")
    
    # 测试价格变化
    print("\n=== 价格变化测试 ===")
    product.price = 6499.0  # 降价
    product.price = 7299.0  # 涨价
    
    # 测试库存变化
    print("\n=== 库存变化测试 ===")
    product.stock = 3   # 低库存
    product.stock = 0   # 缺货
    product.stock = 50  # 补货
    
    # 查看观察者收集的数据
    print("\n=== 观察者数据汇总 ===")
    print(f"价格历史记录数: {len(price_monitor.get_price_history())}")
    print(f"库存警报数: {len(stock_alert.get_alerts())}")
    print(f"分析数据: {sales_analyzer.get_analytics()}")
    
    # 移除观察者
    print("\n=== 移除观察者测试 ===")
    product.detach(price_monitor)
    print(f"移除价格监控后观察者数量: {product.get_observer_count()}")
    
    product.price = 6999.0  # 这次价格监控器不会收到通知


def demonstrate_event_system():
    """
    演示Python事件系统
    """
    print("\n=== Python事件系统演示 ===")
    
    event_system = EventSystem()
    
    # 定义事件处理函数
    def on_user_login(event_data):
        print(f"🔐 用户登录: {event_data['data']['user_id']} at {event_data['timestamp']}")
    
    def on_user_logout(event_data):
        print(f"🚪 用户登出: {event_data['data']['user_id']} at {event_data['timestamp']}")
    
    def on_any_event(event_data):
        print(f"📋 全局监听: {event_data['type']} 事件")
    
    def high_priority_handler(event_data):
        print(f"⚡ 高优先级处理: {event_data['type']}")
    
    # 注册事件监听器
    event_system.on('user_login', on_user_login)
    event_system.on('user_logout', on_user_logout)
    event_system.on('user_login', high_priority_handler, priority=10)  # 高优先级
    event_system.on_any(on_any_event)
    
    print(f"\n注册的监听器数量: {event_system.get_listener_count()}")
    
    # 触发事件
    print("\n触发用户登录事件:")
    event_system.emit('user_login', {'user_id': 'user123', 'ip': '192.168.1.1'})
    
    print("\n触发用户登出事件:")
    event_system.emit('user_logout', {'user_id': 'user123', 'duration': 3600})
    
    print("\n触发自定义事件:")
    event_system.emit('custom_event', {'message': 'Hello World'})
    
    # 移除监听器
    event_system.off('user_login', on_user_login)
    print(f"\n移除监听器后数量: {event_system.get_listener_count()}")


def demonstrate_observable_model():
    """
    演示可观察模型
    """
    print("\n=== 可观察模型演示 ===")
    
    # 创建用户
    user = User("U001", "张三", "zhangsan@example.com")
    
    # 定义事件处理器
    def on_name_changed(event_data):
        data = event_data['data']
        print(f"👤 姓名变更: {data['old_value']} -> {data['new_value']}")
    
    def on_email_changed(event_data):
        data = event_data['data']
        print(f"📧 邮箱变更: {data['old_value']} -> {data['new_value']}")
    
    def on_status_changed(event_data):
        data = event_data['data']
        print(f"🔄 状态变更: {data['old_value']} -> {data['new_value']}")
    
    def on_user_login(event_data):
        data = event_data['data']
        print(f"🔑 用户登录: {data['user_id']}, 第{data['login_count']}次")
    
    # 注册事件监听器
    user.on('name_changed', on_name_changed)
    user.on('email_changed', on_email_changed)
    user.on('status_changed', on_status_changed)
    user.on('user_login', on_user_login)
    
    print(f"\n初始用户: {user}")
    
    # 测试属性变化
    print("\n=== 属性变化测试 ===")
    user.name = "李四"
    user.email = "lisi@example.com"
    user.status = "inactive"
    
    # 测试用户登录
    print("\n=== 用户登录测试 ===")
    user.login()
    user.login()
    user.login()


async def demonstrate_async_observer():
    """
    演示异步观察者模式
    """
    print("\n=== 异步观察者模式演示 ===")
    
    # 创建异步主题
    async_subject = AsyncSubject()
    
    # 创建异步观察者
    email_notifier = AsyncEmailNotifier("邮件服务")
    log_writer = AsyncLogWriter("日志服务")
    
    # 注册观察者
    async_subject.attach(email_notifier)
    async_subject.attach(log_writer)
    
    print("\n开始异步通知测试...")
    
    # 测试异步通知
    events = [
        "用户注册",
        "订单创建",
        "支付完成",
        "商品发货"
    ]
    
    for event in events:
        print(f"\n触发事件: {event}")
        await async_subject.notify_async(event)
        await asyncio.sleep(0.1)  # 短暂延迟
    
    print(f"\n邮件发送记录: {len(email_notifier.sent_emails)}")
    print(f"日志记录数: {len(log_writer.logs)}")


def demonstrate_java_comparison():
    """
    Java对比演示
    
    Java等价代码：
    ```java
    // Java版本的观察者模式
    import java.util.Observable;
    import java.util.Observer;
    
    public class Product extends Observable {
        private String name;
        private double price;
        
        public void setPrice(double price) {
            if (this.price != price) {
                this.price = price;
                setChanged();
                notifyObservers(new PriceChangeEvent(price));
            }
        }
    }
    
    public class PriceMonitor implements Observer {
        @Override
        public void update(Observable o, Object arg) {
            if (arg instanceof PriceChangeEvent) {
                PriceChangeEvent event = (PriceChangeEvent) arg;
                System.out.println("Price changed: " + event.getNewPrice());
            }
        }
    }
    
    // 使用
    Product product = new Product();
    PriceMonitor monitor = new PriceMonitor();
    product.addObserver(monitor);
    product.setPrice(100.0);
    ```
    
    Python优势：
    1. 更灵活的事件系统
    2. 支持函数作为观察者
    3. 装饰器简化属性观察
    4. 异步观察者支持
    """
    print("\n=== Java对比说明 ===")
    print("\nPython优势：")
    print("1. 更灵活的事件系统")
    print("2. 支持函数作为观察者")
    print("3. 装饰器简化属性观察")
    print("4. 异步观察者支持")
    print("5. 动态事件类型")
    
    print("\nJava特点：")
    print("1. Observable类和Observer接口")
    print("2. 类型安全的事件处理")
    print("3. 编译时检查")
    print("4. 需要继承Observable类")


def performance_comparison():
    """
    性能对比测试
    """
    import time
    
    print("\n=== 性能对比 ===")
    
    # 创建大量观察者的产品
    product = Product("PERF_TEST", "性能测试产品", 100.0, 1000)
    
    # 添加大量观察者
    observers = []
    for i in range(100):
        observer = PriceMonitor(f"监控器{i}")
        product.attach(observer)
        observers.append(observer)
    
    print(f"观察者数量: {product.get_observer_count()}")
    
    # 测试通知性能
    start_time = time.time()
    for i in range(100):
        product.price = 100.0 + i
    traditional_time = time.time() - start_time
    
    # 测试事件系统性能
    event_system = EventSystem()
    
    def dummy_handler(event_data):
        pass
    
    # 添加大量监听器
    for i in range(100):
        event_system.on('test_event', dummy_handler)
    
    start_time = time.time()
    for i in range(100):
        event_system.emit('test_event', {'data': i})
    event_system_time = time.time() - start_time
    
    print(f"传统观察者模式 (100次通知): {traditional_time:.4f}秒")
    print(f"事件系统 (100次事件): {event_system_time:.4f}秒")
    print(f"性能差异: {abs(traditional_time - event_system_time):.4f}秒")


async def main():
    """主函数"""
    demonstrate_traditional_observer()
    demonstrate_event_system()
    demonstrate_observable_model()
    await demonstrate_async_observer()
    demonstrate_java_comparison()
    performance_comparison()


if __name__ == "__main__":
    asyncio.run(main())